<template>
  <div class="editor-container">
    <h2>
      <i class="icon">✏️</i>
     编辑器
    </h2>
    
    <div class="editor-wrapper">
      <QuillEditor
        ref="quillEditorRef"
        :content="localContent"
        :options="editorOptions"
        content-type="html"
        theme="snow"
        @update:content="handleUpdate"
        class="quill-editor"
      />
    </div>
    
    <!-- 上传进度条 -->
    <div v-if="uploadProgress > 0 && uploadProgress < 100" class="upload-progress-bar">
      <div class="progress-bar-container">
        <div class="progress-bar-fill" :style="{ width: uploadProgress + '%' }"></div>
      </div>
      <span class="progress-text">上传中: {{ uploadProgress }}%</span>
    </div>

    <div class="editor-info">
      <span class="info-item">
        <i class="icon">📊</i>
        字符数: {{ characterCount }}
      </span>
      <span class="info-item">
        <i class="icon">📝</i>
        字数: {{ wordCount }}
      </span>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import Quill from 'quill'
import toast from '../utils/toast.js'
import { uploadImage as uploadImageApi } from '../api/article.js'
import { getAccessToken } from '../utils/request.js'
import { PROXY_CONFIG } from '../api/config.js'

const props = defineProps({
  content: {
    type: String,
    default: ''
  }
})

const emit = defineEmits(['update:content'])

const localContent = ref('')
const quillEditorRef = ref(null)
const uploadProgress = ref(0)

// 代理服务器基础URL（从统一配置中获取）
const PROXY_BASE_URL = PROXY_CONFIG.WECHAT_IMAGE

// 存储微信图片URL到Blob URL的映射
const imageBlobMap = new Map()

// 判断是否是微信图片URL
const isWechatImageUrl = (url) => {
  return url && (url.includes('mmbiz.qpic.cn') || url.includes('wx.qlogo.cn') || url.includes('thirdwx.qlogo.cn'))
}

// 判断是否是Blob URL
const isBlobUrl = (url) => {
  return url && url.startsWith('blob:')
}

// 通过代理获取图片并转换为Blob URL（自动携带token在header中）
const fetchImageAsBlob = async (imageUrl) => {
  try {
    const token = getAccessToken()
    const headers = {}
    
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }
    
    const response = await fetch(`${PROXY_BASE_URL}?url=${encodeURIComponent(imageUrl)}`, {
      headers
    })
    
    if (!response.ok) {
      throw new Error(`Failed to fetch image: ${response.status}`)
    }
    
    const blob = await response.blob()
    const blobUrl = URL.createObjectURL(blob)
    
    // 保存映射关系（Blob URL -> 原始微信URL）
    imageBlobMap.set(blobUrl, imageUrl)
    
    return blobUrl
  } catch (error) {
    console.error('获取图片失败:', error)
    return imageUrl // 失败时返回原始URL
  }
}

// 将微信图片URL转换为Blob URL
const addProxyPrefix = async (url) => {
  if (isWechatImageUrl(url) && !isBlobUrl(url)) {
    return await fetchImageAsBlob(url)
  }
  return url
}

// 从Blob URL还原为原始微信URL
const removeProxyPrefix = (url) => {
  if (isBlobUrl(url)) {
    return imageBlobMap.get(url) || url
  }
  return url
}

// 将HTML内容中的所有微信图片URL添加代理前缀
const addProxyPrefixToContent = async (html) => {
  if (!html) return ''
  
  const temp = document.createElement('div')
  temp.innerHTML = html
  
  // 转换所有图片src
  const imgElements = temp.querySelectorAll('img')
  for (const img of imgElements) {
    const originalSrc = img.getAttribute('src')
    if (originalSrc) {
      const blobUrl = await addProxyPrefix(originalSrc)
      img.setAttribute('src', blobUrl)
    }
  }
  
  return temp.innerHTML
}

// 将HTML内容中的所有代理URL移除前缀，还原为原始微信URL
const removeProxyPrefixFromContent = (html) => {
  if (!html) return ''
  
  const temp = document.createElement('div')
  temp.innerHTML = html
  
  // 还原所有图片src
  temp.querySelectorAll('img').forEach(img => {
    const proxySrc = img.getAttribute('src')
    if (proxySrc) {
      img.setAttribute('src', removeProxyPrefix(proxySrc))
    }
  })
  
  return temp.innerHTML
}

// 模拟上传进度
const simulateUploadProgress = () => {
  return new Promise((resolve) => {
    uploadProgress.value = 0
    const interval = setInterval(() => {
      uploadProgress.value += Math.random() * 30
      if (uploadProgress.value >= 90) {
        uploadProgress.value = 90
        clearInterval(interval)
        resolve()
      }
    }, 200)
  })
}

// 上传图片到服务器（使用带token认证的API）
const uploadImage = async (file) => {
  // 硬编码的 access_token（实际项目中应该从配置或状态管理中获取）
  const access_token = '97_N-dbna4hiQ7vqTPCoYHGhmk_4lSBHxn6dZZr4pMP_JVbMH9ZtVqTmrMa1I_9w6yjDmxdScuPmr2zw_S3WEcy8q-nGGJvPiQ3Kf0BpVx5JAfeIdgLtOOa8-JT8N4WPVgAEASLR'
  
  try {
    // 开始模拟上传进度
    const progressPromise = simulateUploadProgress()
    
    // 使用带token认证的API接口
    const uploadPromise = uploadImageApi(file, access_token)
    
    // 等待上传完成
    const data = await uploadPromise
    
    // 等待进度条达到90%
    await progressPromise
    
    // 上传完成，进度设为100%
    uploadProgress.value = 100
    
    console.log('上传返回数据:', data)
    
    // 延迟隐藏进度条
    setTimeout(() => {
      uploadProgress.value = 0
    }, 500)
    
    // 返回格式: { errcode, errmsg, media_id, url }
    if (data.url) {
      return data.url
    }
    
    // 如果有错误码，显示错误信息
    if (data.errcode) {
      throw new Error(`上传失败: errcode=${data.errcode}, errmsg=${data.errmsg}`)
    }
    
    throw new Error('上传返回数据格式错误或没有URL')
  } catch (error) {
    // 上传失败，重置进度条
    uploadProgress.value = 0
    console.error('图片上传失败:', error)
    throw error
  }
}

// 存储本地URL和服务器URL的映射关系
const imageUrlMap = new Map()

// 创建加载占位图（转圈动画的SVG）
const createLoadingPlaceholder = () => {
  const svg = `data:image/svg+xml,${encodeURIComponent(`
    <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="40" stroke="#667eea" stroke-width="8" fill="none" stroke-dasharray="60 200" stroke-linecap="round">
        <animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" dur="1s" repeatCount="indefinite"/>
      </circle>
      <text x="50" y="55" text-anchor="middle" fill="#667eea" font-size="12" font-family="Arial">上传中...</text>
    </svg>
  `)}`
  return svg
}

// 自定义图片处理器
const imageHandler = function() {
  const input = document.createElement('input')
  input.setAttribute('type', 'file')
  input.setAttribute('accept', 'image/*')
  input.click()

  input.onchange = async () => {
    const file = input.files[0]
    if (!file) return

    // 检查文件大小（限制 5MB）
    if (file.size > 5 * 1024 * 1024) {
      toast.warning('图片大小不能超过 5MB，请选择较小的图片')
      return
    }

    // 检查文件类型
    if (!file.type.startsWith('image/')) {
      toast.warning('请选择图片文件')
      return
    }

    const quill = quillEditorRef.value.getQuill()
    const range = quill.getSelection(true)
    
    // 1. 先插入加载占位图
    const loadingPlaceholder = createLoadingPlaceholder()
    quill.insertEmbed(range.index, 'image', loadingPlaceholder)
    quill.setSelection(range.index + 1)
    
    // 2. 读取文件为 base64 用于本地预览
    const reader = new FileReader()
    reader.onload = async (e) => {
      const base64Url = e.target.result
      
      // 3. 后台上传到服务器
      try {
        const serverUrl = await uploadImage(file)
        console.log('✅ 图片上传成功，服务器URL:', serverUrl)
        
        if (!serverUrl || serverUrl.trim() === '') {
          throw new Error('服务器返回的URL为空')
        }
        
        // 4. 上传成功，替换加载图为真实图片
        const delta = quill.getContents()
        let imageIndex = -1
        
        // 查找加载占位图的位置
        delta.ops.forEach((op, index) => {
          if (op.insert && op.insert.image === loadingPlaceholder) {
            imageIndex = delta.ops.slice(0, index).reduce((pos, op) => {
              if (typeof op.insert === 'string') return pos + op.insert.length
              return pos + 1
            }, 0)
          }
        })
        
        if (imageIndex !== -1) {
          // 删除加载图，插入真实图片
          quill.deleteText(imageIndex, 1)
          quill.insertEmbed(imageIndex, 'image', base64Url)
          quill.setSelection(imageIndex + 1)
        }
        
        // 5. 保存映射关系（base64 -> 服务器URL）
        imageUrlMap.set(base64Url, serverUrl)
        
        console.log('✅ 映射已保存，编辑器显示base64，保存时会转为服务器URL')
      } catch (error) {
        console.error('❌ 图片上传失败:', error)
        toast.error('图片上传失败：' + error.message)
        
        // 上传失败，删除加载占位图
        const delta = quill.getContents()
        let imageIndex = -1
        
        delta.ops.forEach((op, index) => {
          if (op.insert && op.insert.image === loadingPlaceholder) {
            imageIndex = delta.ops.slice(0, index).reduce((pos, op) => {
              if (typeof op.insert === 'string') return pos + op.insert.length
              return pos + 1
            }, 0)
          }
        })
        
        if (imageIndex !== -1) {
          quill.deleteText(imageIndex, 1)
        }
      }
    }
    
    reader.readAsDataURL(file)
  }
}

// 编辑器配置选项
const editorOptions = {
  modules: {
    toolbar: {
      container: [
        ['bold', 'italic', 'underline', 'strike'],
        ['blockquote', 'code-block'],
        [{ 'header': 1 }, { 'header': 2 }],
        [{ 'list': 'ordered'}, { 'list': 'bullet' }],
        [{ 'script': 'sub'}, { 'script': 'super' }],
        [{ 'indent': '-1'}, { 'indent': '+1' }],
        [{ 'direction': 'rtl' }],
        [{ 'size': ['small', false, 'large', 'huge'] }],
        [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
        [{ 'color': [] }, { 'background': [] }],
        [{ 'font': [] }],
        [{ 'align': [] }],
        ['clean'],
        ['link', 'image', 'video']
      ],
      handlers: {
        image: imageHandler
      }
    }
  },
  placeholder: '请输入内容...',
  readOnly: false
}

// 计算字符数
const characterCount = computed(() => {
  if (!localContent.value) return 0
  const temp = document.createElement('div')
  temp.innerHTML = localContent.value
  const text = temp.textContent || temp.innerText || ''
  return text.length
})

// 计算字数（中文字符和英文单词）
const wordCount = computed(() => {
  if (!localContent.value) return 0
  const temp = document.createElement('div')
  temp.innerHTML = localContent.value
  const text = temp.textContent || temp.innerText || ''
  
  // 匹配中文字符和英文单词
  const chineseChars = text.match(/[\u4e00-\u9fa5]/g) || []
  const englishWords = text.match(/[a-zA-Z]+/g) || []
  
  return chineseChars.length + englishWords.length
})

// 处理内容更新
const handleUpdate = (content) => {
  // 直接emit原始内容，不做转换
  emit('update:content', content)
}

// 将 Quill 非标准 class 转换为标准 HTML 内联样式
const convertQuillClassesToInlineStyles = (html) => {
  const temp = document.createElement('div')
  temp.innerHTML = html
  
  // 处理对齐方式 - 转换为标准的 text-align 样式
  temp.querySelectorAll('[class*="ql-align"]').forEach(el => {
    if (el.classList.contains('ql-align-center')) {
      el.style.textAlign = 'center'
    } else if (el.classList.contains('ql-align-right')) {
      el.style.textAlign = 'right'
    } else if (el.classList.contains('ql-align-justify')) {
      el.style.textAlign = 'justify'
    }
    // 移除 Quill 特定的 class
    el.className = el.className.replace(/ql-align-\w+/g, '').trim()
  })
  
  // 处理缩进 - 转换为标准的 padding-left 样式
  temp.querySelectorAll('[class*="ql-indent"]').forEach(el => {
    const match = el.className.match(/ql-indent-(\d+)/)
    if (match) {
      const level = parseInt(match[1])
      el.style.paddingLeft = `${level * 3}em`
      el.className = el.className.replace(/ql-indent-\d+/g, '').trim()
    }
  })
  
  // 处理字体大小 - 转换为标准的 font-size 样式
  temp.querySelectorAll('[class*="ql-size"]').forEach(el => {
    if (el.classList.contains('ql-size-small')) {
      el.style.fontSize = '0.75em'
    } else if (el.classList.contains('ql-size-large')) {
      el.style.fontSize = '1.5em'
    } else if (el.classList.contains('ql-size-huge')) {
      el.style.fontSize = '2.5em'
    }
    el.className = el.className.replace(/ql-size-\w+/g, '').trim()
  })
  
  // 处理字体 - 转换为标准的 font-family 样式
  temp.querySelectorAll('[class*="ql-font"]').forEach(el => {
    const match = el.className.match(/ql-font-(\w+)/)
    if (match) {
      el.style.fontFamily = match[1]
      el.className = el.className.replace(/ql-font-\w+/g, '').trim()
    }
  })
  
  // 移除所有空的 class 属性
  temp.querySelectorAll('[class=""]').forEach(el => {
    el.removeAttribute('class')
  })
  
  return temp.innerHTML
}

// 获取最终内容（将base64转换为服务器URL，移除代理前缀，转换非标准样式为标准HTML）- 供父组件在保存时调用
const getContentWithServerUrls = () => {
  const quill = quillEditorRef.value?.getQuill()
  if (!quill) return ''
  
  let content = quill.root.innerHTML
  
  // 1. 将所有base64 URL替换为服务器URL
  imageUrlMap.forEach((serverUrl, base64Url) => {
    const escapedBase64 = base64Url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
    content = content.replace(new RegExp(escapedBase64, 'g'), serverUrl)
  })
  
  // 2. 移除所有代理前缀，还原为原始微信URL
  content = removeProxyPrefixFromContent(content)
  
  // 3. 将 Quill 非标准 class 转换为标准 HTML 内联样式
  content = convertQuillClassesToInlineStyles(content)
  
  console.log('✅ 最终保存：base64已转为服务器URL，代理前缀已移除，Quill class已转为标准HTML样式')
  console.log('映射数量:', imageUrlMap.size)
  console.log('HTML 内容预览:', content.substring(0, 500))
  
  return content
}

// 暴露方法给父组件
defineExpose({
  getContentWithServerUrls
})

// 监听外部内容变化 - 加载时添加代理前缀
watch(() => props.content, async (newVal) => {
  // 将原始内容（微信URL）转换为Blob URL
  const contentWithProxy = await addProxyPrefixToContent(newVal)
  if (contentWithProxy !== localContent.value) {
    localContent.value = contentWithProxy
    console.log('✅ 编辑器加载内容：已将微信图片转换为Blob URL（token在header中）')
  }
}, { immediate: true })

// 处理粘贴事件
const handlePaste = async (e) => {
  const clipboardData = e.clipboardData || window.clipboardData
  const items = clipboardData.items
  
  if (!items) return
  
  // 遍历剪贴板项目
  for (let i = 0; i < items.length; i++) {
    const item = items[i]
    
    // 检查是否是图片
    if (item.type.indexOf('image') !== -1) {
      e.preventDefault() // 阻止默认粘贴行为
      
      const file = item.getAsFile()
      if (!file) continue
      
      // 检查文件大小（限制 5MB）
      if (file.size > 5 * 1024 * 1024) {
        toast.warning('图片大小不能超过 5MB，请选择较小的图片')
        continue
      }
      
      const quill = quillEditorRef.value.getQuill()
      const range = quill.getSelection(true)
      
      // 1. 先插入加载占位图
      const loadingPlaceholder = createLoadingPlaceholder()
      quill.insertEmbed(range.index, 'image', loadingPlaceholder)
      quill.setSelection(range.index + 1)
      console.log('✅ 粘贴图片：加载动画已插入')
      
      // 2. 读取文件为 base64
      const reader = new FileReader()
      reader.onload = async (event) => {
        const base64Url = event.target.result
        
        // 3. 后台上传到服务器
        try {
          const serverUrl = await uploadImage(file)
          console.log('✅ 粘贴的图片上传成功，服务器URL:', serverUrl)
          
          if (!serverUrl || serverUrl.trim() === '') {
            throw new Error('服务器返回的URL为空')
          }
          
          // 4. 上传成功，替换加载图为真实图片
          const delta = quill.getContents()
          let imageIndex = -1
          
          // 查找加载占位图的位置
          delta.ops.forEach((op, index) => {
            if (op.insert && op.insert.image === loadingPlaceholder) {
              imageIndex = delta.ops.slice(0, index).reduce((pos, op) => {
                if (typeof op.insert === 'string') return pos + op.insert.length
                return pos + 1
              }, 0)
            }
          })
          
          if (imageIndex !== -1) {
            // 删除加载图，插入真实图片
            quill.deleteText(imageIndex, 1)
            quill.insertEmbed(imageIndex, 'image', base64Url)
            quill.setSelection(imageIndex + 1)
          }
          
          // 5. 保存映射关系（base64 -> 服务器URL）
          imageUrlMap.set(base64Url, serverUrl)
          
          console.log('✅ 粘贴图片映射已保存')
        } catch (error) {
          console.error('❌ 粘贴的图片上传失败:', error)
          toast.error('图片上传失败：' + error.message)
          
          // 上传失败，删除加载占位图
          const delta = quill.getContents()
          let imageIndex = -1
          
          delta.ops.forEach((op, index) => {
            if (op.insert && op.insert.image === loadingPlaceholder) {
              imageIndex = delta.ops.slice(0, index).reduce((pos, op) => {
                if (typeof op.insert === 'string') return pos + op.insert.length
                return pos + 1
              }, 0)
            }
          })
          
          if (imageIndex !== -1) {
            quill.deleteText(imageIndex, 1)
          }
        }
      }
      
      reader.readAsDataURL(file)
    }
  }
}

// 组件挂载后绑定ref和粘贴事件
onMounted(() => {
  // 确保编辑器已初始化
  console.log('✅ 富文本编辑器已挂载')
  
  // 监听编辑器的粘贴事件
  const quill = quillEditorRef.value?.getQuill()
  if (quill) {
    const editor = quill.root
    editor.addEventListener('paste', handlePaste)
    console.log('✅ 图片粘贴监听已绑定')
  }
})
</script>

<style scoped>
.editor-container {
  background: white;
  border-radius: 12px;
  padding: 25px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

.editor-container h2 {
  margin: 0 0 20px 0;
  color: #333;
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  gap: 10px;
}

.icon {
  font-style: normal;
}

.editor-wrapper {
  margin-bottom: 15px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid #e0e0e0;
}

.quill-editor {
  min-height: 400px;
}

:deep(.ql-toolbar) {
  background: #f8f9fa;
  border: none;
  border-bottom: 1px solid #e0e0e0;
  padding: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

:deep(.ql-toolbar .ql-formats) {
  margin-right: 8px;
  margin-bottom: 5px;
}

:deep(.ql-container) {
  border: none;
  font-size: 16px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

:deep(.ql-editor) {
  min-height: 350px;
  padding: 20px;
}

:deep(.ql-editor.ql-blank::before) {
  color: #adb5bd;
  font-style: normal;
}

/* 编辑器中的图片样式 */
:deep(.ql-editor img) {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 10px 0;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

:deep(.ql-snow .ql-stroke) {
  stroke: #667eea;
}

:deep(.ql-snow .ql-fill) {
  fill: #667eea;
}

:deep(.ql-snow .ql-picker-label) {
  color: #667eea;
}

:deep(.ql-toolbar button:hover),
:deep(.ql-toolbar button:focus),
:deep(.ql-toolbar button.ql-active) {
  color: #667eea;
}

:deep(.ql-toolbar button:hover .ql-stroke),
:deep(.ql-toolbar button:focus .ql-stroke),
:deep(.ql-toolbar button.ql-active .ql-stroke) {
  stroke: #667eea;
}

:deep(.ql-toolbar button:hover .ql-fill),
:deep(.ql-toolbar button:focus .ql-fill),
:deep(.ql-toolbar button.ql-active .ql-fill) {
  fill: #667eea;
}

.editor-info {
  display: flex;
  gap: 20px;
  padding: 10px 15px;
  background: #f8f9fa;
  border-radius: 8px;
  color: #666;
  font-size: 14px;
}

.info-item {
  display: flex;
  align-items: center;
  gap: 5px;
  font-weight: 500;
}

/* 上传进度条样式 */
.upload-progress-bar {
  margin-bottom: 15px;
  padding: 12px 15px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.progress-bar-container {
  width: 100%;
  height: 8px;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-bar-fill {
  height: 100%;
  background: white;
  border-radius: 10px;
  transition: width 0.3s ease;
  box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}

.progress-text {
  display: block;
  text-align: center;
  color: white;
  font-size: 13px;
  font-weight: 600;
}

/* 移动端优化 */
@media (max-width: 768px) {
  .editor-container {
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  }

  .editor-container h2 {
    font-size: 1.2rem;
    margin-bottom: 15px;
  }

  .quill-editor {
    min-height: 300px;
  }

  :deep(.ql-toolbar) {
    padding: 8px 5px;
  }

  :deep(.ql-toolbar .ql-formats) {
    margin-right: 5px;
    margin-bottom: 3px;
  }

  /* 工具栏按钮优化 */
  :deep(.ql-toolbar button) {
    width: 32px;
    height: 32px;
    padding: 3px;
  }

  :deep(.ql-toolbar .ql-picker) {
    font-size: 13px;
  }

  :deep(.ql-toolbar .ql-picker-label) {
    padding: 2px 5px;
  }

  /* 编辑器内容区域 */
  :deep(.ql-editor) {
    min-height: 250px;
    padding: 15px;
    font-size: 15px;
  }

  /* 下拉选择器优化 */
  :deep(.ql-snow .ql-picker.ql-expanded .ql-picker-options) {
    max-height: 200px;
    overflow-y: auto;
  }

  .editor-info {
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    font-size: 13px;
  }

  .info-item {
    justify-content: center;
  }
}

/* 超小屏幕优化 */
@media (max-width: 480px) {
  .editor-container {
    padding: 10px;
  }

  .editor-container h2 {
    font-size: 1.1rem;
  }

  :deep(.ql-toolbar button) {
    width: 28px;
    height: 28px;
  }

  :deep(.ql-editor) {
    min-height: 200px;
    padding: 12px;
    font-size: 14px;
  }

  .quill-editor {
    min-height: 250px;
  }
}
</style>
